﻿using SmallJob.Model;
using SmallJob.Services.Code;
using SmallJob.Services.Interfaces;
using SmallShop.Services.Code;
using SmallShop.Services.Interfaces;
using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Security;
using Caching;
using System.Collections.Generic;
using System.Linq;

namespace FrontEnd.Controllers
{
    public class UserController : Controller
    {
        private readonly IEmailFormatService _EmailFormatService;

        private readonly IOfferMessageService _OfferMessageService;

        private readonly IOfferService _OfferService;

        private readonly IOrderService _OrderService;

        private readonly IProvideService _ProvideService;

        private readonly IRequestService _RequestService;

        private readonly ISkillService _SkillService;

        private readonly IFollowerService _FollowerService;

        //
        // GET: /User/
        private readonly IUserService _UserService;

        public UserController(IUserService UserService, IOfferService OfferService, IRequestService RequestService, IProvideService ProvideService, IOfferMessageService OfferMessageService, IOrderService OrderService, ISkillService SkillService, IEmailFormatService EmailFormatService, IFollowerService FollowerService)
        {
            _UserService = UserService;
            _OfferService = OfferService;
            _RequestService = RequestService;
            _ProvideService = ProvideService;
            _OfferMessageService = OfferMessageService;
            _OrderService = OrderService;
            this._SkillService = SkillService;
            this._EmailFormatService = EmailFormatService;
            _FollowerService = FollowerService;
        }

        public ActionResult AddAjax()
        {
            string email = Request.Form["email"];
            string password = Request.Form["password"];
            if (!string.IsNullOrWhiteSpace(email))
            {
                if (!string.IsNullOrWhiteSpace(password))
                {
                    SmallJob.Model.User user = new SmallJob.Model.User();
                    user.Password = password;
                    user.Email = email;
                    email = "";
                    password = "";
                    //partten
                    string pattern = @"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}";
                    Regex regex = new Regex(pattern);
                    if (_UserService.GetByEmail(user.Email) != null)
                    {
                        ModelState.AddModelError("EmailInvalid", "Email đã tồn tại");
                        email = "Email đã tồn tại";
                    }
                    if (string.IsNullOrWhiteSpace(user.Password) || user.Password.Length < 6)
                    {
                        ModelState.AddModelError("PasswordInvalid", "Mật khẩu gồm ít nhất 6 kí tự");
                        password = "Mật khẩu gồm ít nhất 6 kí tự";
                    }
                    if (!regex.IsMatch(user.Email))
                    {
                        ModelState.AddModelError("EmailInvalid", "Email không đúng");
                        email = "Email không đúng";
                    }

                    if (ModelState.IsValid)
                    {
                        user.JoinDate = DateTime.Now;
                        user.Password = UserUtility.Encrypt(user.Password, user.Email);
                        user.VerifyCode = UserUtility.GetRandomString(10);
                        user.ProperName = user.Email.Split('@')[0];
                        _UserService.Add(user);
                        MemCache.InsertCache("user_" + (user.UserName ?? user.ID.ToString()), user);
                        FormsAuthentication.SetAuthCookie(user.Email, false);
                        //try catch to enable and disable send email depend on resource
                        try
                        {
                            var format = _EmailFormatService.GetById(Convert.ToInt32(Resources.Resource.NotifyEmailVerifyCode));
                            DictionaryVerifyCode diccode = new DictionaryVerifyCode(user.Email, user.VerifyCode);
                            UserUtility.NotifyEmail(format, diccode);
                        }
                        catch (Exception) {   }
                        return Json(true);
                    }
                }
                else
                {
                    email = "";
                    password = "Mật khẩu không được bỏ trống.";
                }
            }
            else
            {
                email = "Email không được bỏ trống.";
                password = "";
            }

            return Json(new { email = email, password = password });
        }

        public ActionResult BetaKey(String betakey)
        {
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                if (betakey == "betaviecnho")
                {
                    u.BetaTester = true;
                    _UserService.Update(u);
                    MemCache.InsertCache("user_" + u.ID.ToString(), u);
                    MemCache.InsertCache("user_" + (u.UserName ?? u.ID.ToString()), u);
                    return Json(true);
                }
            }
            return Json(false);
        }
        // Đổi mô tả bản thân
        [ValidateInput(false)]
        public ActionResult ChangeInfo(String info)
        {
            if (User.Identity.IsAuthenticated)
            {
                var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                user.Info = HttpUtility.HtmlEncode(info);
                _UserService.Update(user);
                MemCache.InsertCache("user_" + user.ID.ToString(), user);
                MemCache.InsertCache("user_" + (user.UserName ?? user.ID.ToString()), user);
                return Json(true);
            }
            return Json(false);
        }

        public ActionResult ChangeSkills(String skills)
        {
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                u.Skill = skills;
                _UserService.Update(u);
                MemCache.InsertCache("user_" + u.ID.ToString(), u);
                MemCache.InsertCache("user_" + (u.UserName ?? u.ID.ToString()), u);
                String[] s = skills.Split(',');
                foreach (var item in s)
                {
                    if (!_SkillService.IsExist(item))
                    {
                        _SkillService.Add(new Skill()
                        {
                            Name = item
                        });
                    }
                }
                return Json(skills.Replace(",", ", "));
            }
            return Json("");
        }

        public ActionResult CheckEmail()
        {
            string email = Request.QueryString["email"];
            var u = _UserService.GetByEmail(email);
            return Json(u != null);
        }

        public ActionResult GetCurrentUser()
        {
            if (User.Identity.IsAuthenticated)
            {
                return Json(_UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name));
            }
            return Json(null);
        }

        public ActionResult GetFBInfo(int ID)
        {
            var u = _UserService.GetById(ID);
            return Json(new { fbID = u.FbID });
        }

        public ActionResult GetSkill()
        {
            String search = Request.QueryString["key"];
            return Json(_SkillService.GetAllSkillName(search).ToArray());
        }

        public ActionResult GetSkillByUser()
        {
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                if (u.Skill != null)
                {
                    return Json(u.Skill.Split(','));
                }
                else
                {
                    return Json("");
                }
            }
            return Json("");
        }

        public ActionResult GoToUserHome()
        {
            if (User.Identity.IsAuthenticated)
            {
                var user = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                return RedirectToAction("Index", new { username = (string.IsNullOrWhiteSpace(user.UserName) ? user.ID.ToString() : user.UserName) });
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }

        public ActionResult Index()
        {
            var username = RouteData.Values["username"].ToString();
            User user = null;
            if (MemCache.Get<User>("user_" + username) == null)
            {
                user = _UserService.GetByUsername(username);
                if (user == null)
                {
                    try
                    {
                        user = _UserService.GetById(Convert.ToInt32(username));
                    }
                    catch (Exception)
                    {
                    }
                }
                if (user == null)
                {
                    return RedirectToAction("Error404", "Error");
                }
                else
                {
                    MemCache.InsertCache("user_" + username, user);
                }
            }
            else
            {
                user = MemCache.Get<User>("user_" + username);
            }
            ViewData["isOwner"] = false;
            ViewData["isFollowwed"] = false;
            ViewData["countfollow"] = _FollowerService.CountFollower(user.ID);
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                if (u.ID == user.ID)
                {
                    ViewData["isOwner"] = true;
                }
                else
                {
                    if (_FollowerService.IsExist(u.ID, user.ID))
                    {
                        ViewData["isFollowwed"] = !_FollowerService.GetByID(u.ID, user.ID).IsDeleted;
                    }
                }
            }
            List<User> listUserFollow = new List<User>();
            var listFollow = _FollowerService.GetFollowUser(user.ID);
            foreach (var item in listFollow)
            {
                var u = _UserService.GetById(item.FollowerID);
                listUserFollow.Add(u);
                MemCache.InsertCache("user_" + (u.UserName ?? u.ID.ToString()), u);
            }
            var services = _ProvideService.GetBuyUserID(user.ID);
            ViewData["listFollowers"] = listUserFollow;
            ViewData["services"] = services;
            var orders = MemCache.Get<List<Order>>("user_comment_" + user.ID);
            if (orders == null)
            {
                orders = new List<Order>();
                if (services.Count > 0)
                {
                    foreach (var item in services)
                    {
                        orders.AddRange(_OrderService.GetOrderComment(item.ID));
                    }
                    foreach (var item in orders)
                    {
                        item.Buyer = _UserService.GetById(item.BuyerID);
                    }
                    orders = orders.OrderByDescending(o => o.ModifiedDate).ToList();
                }
                MemCache.InsertCache("user_comment_" + user.ID, orders);
            }
            ViewData["comment"] = orders;
            var requests = MemCache.Get<List<Request>>("user_request_" + user.ID);
            if (requests == null)
            {
                requests = _RequestService.GetRequestByUserID(user.ID);
                MemCache.InsertCache("user_request_" + user.ID, requests);
            }
            ViewData["requests"] = requests;
            return View(user);
        }

        public ActionResult SavePassword()
        {
            if (!User.Identity.IsAuthenticated)
                return RedirectToAction("Index", "Home");
            string oldpass = Request.Form["oldpass"];
            var user = _UserService.GetByEmail(User.Identity.Name);
            if (user.Password != UserUtility.Encrypt(oldpass, User.Identity.Name))
            {
                ModelState.AddModelError("OldPasswordInvalid", "Mật khẩu không đúng");
            }
            string newpass = Request.Form["newpass"];
            string repass = Request.Form["repass"];
            if (string.IsNullOrWhiteSpace(newpass) || newpass.Length < 6)
                ModelState.AddModelError("NewPasswordInvalid", "Mật khẩu gồm ít nhất 6 kí tự");
            if (newpass != repass)
                ModelState.AddModelError("RePasswordInvalid", "Mật khẩu nhập lại không đúng");
            if (ModelState.IsValid)
            {
                user.Password = UserUtility.Encrypt(newpass, User.Identity.Name);
                _UserService.Update(user);
                return RedirectToAction("Index", "Home");
            }
            return View("ChangePassword");
        }

        public ActionResult UploadAvatar(HttpPostedFileBase avatarImage)
        {
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                if (avatarImage != null && avatarImage.ContentLength != 0)
                {
                    DateTime dt = DateTime.Now;
                    // extract only the fielname
                    var fileName = Path.GetFileName(avatarImage.FileName);
                    Regex regex = new Regex(Resources.Resource.RegexRemoveCharacter);
                    fileName = regex.Replace(fileName, "");
                    // upload anh vao folder
                    var path = Path.Combine(UserUtility.GetFolderAvatarUpload() + u.ID, dt.ToBinary() + "_" + fileName);
                    if (!Directory.Exists(UserUtility.GetFolderAvatarUpload() + u.ID))
                    {
                        Directory.CreateDirectory(UserUtility.GetFolderAvatarUpload() + u.ID);
                    }
                    avatarImage.SaveAs(path);
                    string imgPath = UserUtility.GetImageAvatarUpload() + u.ID + "/" + dt.ToBinary() + "_" + fileName;
                    u.Avatar = imgPath;
                    //thangtt add verify
                    VerifyAccount va = new VerifyAccount(u.VerifyStatus, true);

                    va.CreateStatusByUSer(u);
                    va.SetStatusOfStep(VerifyAccount.STEP_AVATAR, true);
                    u.VerifyStatus = va.GetVerifyStatus();
                    _UserService.Update(u);
                    MemCache.InsertCache("user_" +  u.ID.ToString(), u);
                    MemCache.InsertCache("user_" + (u.UserName ?? u.ID.ToString()), u);
                    var percentdone = va.GetPercentDone();
                    return Json(new { imagePath = imgPath, percentdone = percentdone });
                }
            }
            return Json("");
        }
        //upload ajax cover
        public ActionResult UploadCover(HttpPostedFileBase imageCover)
        {
            if (User.Identity.IsAuthenticated)
            {
                var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
                if (imageCover != null && imageCover.ContentLength != 0)
                {
                    DateTime dt = DateTime.Now;
                    // extract only the fielname
                    var fileName = Path.GetFileName(imageCover.FileName);
                    Regex regex = new Regex(Resources.Resource.RegexRemoveCharacter);
                    fileName = regex.Replace(fileName, "");
                    // upload anh vao folder
                    var path = Path.Combine(UserUtility.GetFolderCoverUpload() + u.ID, dt.ToBinary() + "_" + fileName);
                    if (!Directory.Exists(UserUtility.GetFolderCoverUpload() + u.ID))
                    {
                        Directory.CreateDirectory(UserUtility.GetFolderCoverUpload() + u.ID);
                    }
                    imageCover.SaveAs(path);
                    WebImage img = new WebImage(path);
                    if (img.Width >= 1200)
                    {
                        if (img.Height > 430)
                        {
                            img.Crop((img.Height - 430) / 2, 0, (img.Height - 430) / 2, 0);
                        }
                        else
                        {
                            img.Resize(img.Width, 430, false);
                        }
                        img.Save(path);
                        string imgPath = UserUtility.GetImageCoverUpload() + u.ID + "/" + dt.ToBinary() + "_" + fileName;
                        u.CoverImage = imgPath;
                        _UserService.Update(u);
                        MemCache.InsertCache("user_" + u.ID.ToString(), u);
                        MemCache.InsertCache("user_" + (u.UserName ?? u.ID.ToString()), u);
                        return Json(imgPath);
                    }
                    else
                    {
                        return Json("smallimage");
                    }
                }
            }
            return Json("");
        }
        public ActionResult AddFollow(int id)
        {
            if (!User.Identity.IsAuthenticated)
            {
                return Json(false);
            }
            var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            if (!_FollowerService.IsExist(u.ID, id))
            {
                var f = new Follower()
                {
                    FollowerID = u.ID,
                    UserID = id,
                    IsDeleted = false,
                    Created = DateTime.Now,
                    Modified = DateTime.Now
                };
                _FollowerService.Add(f);
                return Json(true);
            }
            else
            {
                var f = _FollowerService.GetByID(u.ID, id);
                f.IsDeleted = false;
                _FollowerService.Update(f);
                return Json(true);
            }

        }
        public ActionResult RemoveFollow(int id)
        {
            if (!User.Identity.IsAuthenticated)
            {
                return Json(false);
            }
            var u = _UserService.GetByFBID(User.Identity.Name) ?? _UserService.GetByEmail(User.Identity.Name);
            if (_FollowerService.IsExist(u.ID, id))
            {
                var f = _FollowerService.GetByID(u.ID, id);
                f.IsDeleted = true;
                _FollowerService.Update(f);
                return Json(true);
            }
            else
            {
                return Json(false);
            }
        }
        public ActionResult CountFollower(int id)
        {
            return Json(_FollowerService.CountFollower(id));
        }
    }
}